﻿using Framework.Base;

using  System.Collections.Generic;
using UnityEditor.Rendering;
using UnityEditor.SceneManagement;
using UnityEngine.PlayerLoop;

namespace Framework.Time
{

    public delegate void TimerDelegate(float deltaTime);
    

    /// <summary>
    ///  定时器对象
    /// </summary>
    public class Timer: Base.BaseObject, IPoolObj
    {
        
        public TimerDelegate handler;
    
        /// <summary>
        ///  是否是循环
        /// </summary>
        public bool isLoop = false;

        /// <summary>
        ///  是否暂停
        /// </summary>
        public bool isPause = false;
    
        /// <summary>
        ///  调用次数 -1 表示无线循环
        /// </summary>
        public int loopCnt = 0;

        /// <summary>
        ///  调用间隔
        /// </summary>
        public float interval = 0f;
        
        /// <summary>
        ///  剩余时间
        /// </summary>
        public float remainTime = 0f;
        
        
        public bool isStop = false;

        public void Stop()
        {
            isStop = true;
            handler = null;
        }

        public void OnFetch()
        {
            isLoop = false;
            isPause = false;
        }

        // 加入回收池
        public  void OnRecycle()
        {
            isStop = true;
            handler = null;
        }


    }
    
    
    /// <summary>
    ///  定时器管理模块
    /// </summary>
    public class TimerMgr : SignalBaseObject<TimerMgr>
    {
        private List<Timer> m_timerList = new List<Timer>();

        public static void Update(float dt)
        {
            instance.UpdateTimer(dt);
        }

        /// <summary>
        /// 添加一个定时器
        /// </summary>
        /// <param name="handler"></param>
        /// <param name="interval"></param>
        /// <param name="delayTime"></param>
        /// <param name="loopCnt"></param>
        /// <returns></returns>
        public static Timer Add(TimerDelegate handler, float interval,float delayTime, int loopCnt)
        {
            return instance.AddTimer(handler, interval, delayTime, loopCnt);
        }
        
        /// <summary>
        /// 移除定时器
        /// </summary>
        /// <param name="timer"></param>
        public static void Remove(Timer timer)
        {
            instance.RemoveTimer(timer);
        }

        public static void Remove(TimerDelegate handler)
        {
            instance.RemoveTimer(handler);
        }

        private Timer AddTimer(TimerDelegate handler, float interval,float delayTime, int loopCnt)
        {
            var timer = PoolMgr.Create<Timer>();
            timer.handler = handler;
            timer.interval = interval;
            timer.loopCnt = loopCnt;
            timer.remainTime = delayTime + interval;
            
            return timer;
        }

        private void RemoveTimer(Timer timer)
        {
            if (!timer.isStop)
            {
                m_timerList.Remove(timer);
                PoolMgr.Recycle(timer);
            }
        }

        private void RemoveTimer(TimerDelegate handler)
        {
            var cnt = m_timerList.Count;
            var index = 0;
            while (cnt > 0)
            {
                var timer = m_timerList[index];
                if (timer.handler.Target == handler.Target)
                {
                    m_timerList.RemoveAt(index);
                    PoolMgr.Recycle(timer);
                }
                else
                {
                    index++;
                }
                cnt--;
            }
        }

        private void UpdateTimer(float dt)
        {
            var cnt = m_timerList.Count;
            var index = 0;
            while (cnt > 0)
            {
                var timer = m_timerList[index];
                if (!timer.isStop && !timer.isPause)
                {
                    var remainTime = timer.remainTime - dt;
                    if (remainTime <= 0)
                    {
                        timer.handler.Invoke(dt);
                        if (timer.loopCnt == -1)
                        {
                            timer.remainTime = remainTime + timer.interval;
                        }
                        else
                        {
                            if ((timer.loopCnt --) <= 0)
                            {
                                timer.isStop = true;
                            }
                        }
                    }
                }
                if (timer.isStop)
                {
                    PoolMgr.Recycle(timer);
                    m_timerList.RemoveAt(index);
                }
                else
                {
                    index++;
                }

                cnt--;
            }
        }
    }


    
}